package jsu.blogger.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class TokenUtil {
    // 自定义密钥，用于生成JWT的签名密钥
    private static final String CUSTOM_SECRET = "this_is_a_god_secret_by_our_project_余小平_徐海东_谢武_xw_xhd_yxp_hhhh_xhd_hhhh_xw_hhhh_yxp";

    // 使用CUSTOM_SECRET生成签名密钥
    private static final SecretKey signKey = createSecretKey(CUSTOM_SECRET);

    // JWT有效期设置为15天（单位：毫秒）
    private static final Long time = 1000L * 60 * 60 * 24 * 15; // 15天有效期

    /**
     * 使用自定义的密钥创建SecretKey对象
     * @param secret 自定义的密钥字符串
     * @return 返回一个HmacSHA256算法的SecretKey对象
     */
    private static SecretKey createSecretKey(String secret) {
        // 使用HmacSHA256算法和指定的密钥创建SecretKey
        return new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
    }

    /**
     * 根据用户ID,密码，一键返回生成的JWT令牌
     * @param uid 用户ID
     * @param password 用户密码
     * @return 返回生成的JWT字符串
     */
    public static String returnToken(Long uid, String password) {
        // 创建JWT的载荷并生成JWT
        return generateJWT(createToken(uid, password));
    }

    /**
     * 创建JWT的载荷（Claims部分），包含用户信息
     * @param uid 用户ID
     * @param password 用户密码
     * @return 返回一个包含uid和password的Map作为JWT的载荷
     */
    public static Map<String, Object> createToken(Long uid, String password) {
        Map<String, Object> claims = new HashMap<>();

        // 将用户ID和密码作为载荷存入JWT
        claims.put("uid", uid.toString());  // 转换为字符串保存
        claims.put("password", password);

        return claims;  // 返回包含用户信息的载荷Map
    }

    /**
     * 生成JWT令牌
     * @param claims JWT的载荷部分，包含用户信息等
     * @return 返回生成的JWT字符串
     */
    public static String generateJWT(Map<String, Object> claims) {
        // 使用Jwts.builder()构建JWT
        return Jwts.builder()
                // 使用签名密钥对JWT进行签名
                .signWith(signKey)
                // 设置JWT的过期时间，这里是当前时间加上15天
                .setExpiration(new Date(System.currentTimeMillis() + time))
                // 将载荷信息添加到JWT
                .addClaims(claims)
                // 生成JWT并返回其字符串形式
                .compact();
    }

    /**
     * 解析JWT令牌并获取其中的Claims（载荷部分）
     * @param jwt JWT令牌字符串
     * @return 返回JWT的载荷部分，即Claims对象
     * @throws Exception 如果JWT无效（过期或签名不匹配），会抛出异常
     */
    public static Claims parseJWT(String jwt) throws Exception {
        // 使用Jwts.parser()解析JWT并验证签名
        return Jwts.parser()
                // 设置用于验证JWT签名的密钥
                .setSigningKey(signKey)
                // 解析JWT并获取其有效载荷（Claims部分）
                .parseClaimsJws(jwt)
                // 获取JWT的载荷部分
                .getBody();
    }
}
